#include <errno.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <sched.h>
#include <signal.h>
#include <time.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <wchar.h>
#include <string.h>

#include <aura.h>
#include <auraplus.h>
#include <linknode.h>

#include "thread.h"

extern struct timeval g_tvStartTime;

extern Aura_ProcessId g_processId;

EXTERN_C Aura_ECode CreateModuleLock();
EXTERN_C void DestroyModuleLock();

EXTERN_C Aura_ECode InitVirtualMemory();
EXTERN_C void DeleVirtualMemory();

DLinkNode g_ThreadInfoList;
static Aura_Handle s_ThreadLock;

typedef struct _ThreadArg {
    PAuraThreadMain m_pEntry;
    Aura_PVoid           m_pArgs;
    Aura_Bool         m_bIsSuspend;
    ThreadInfo*     m_pThreadInfo;
}ThreadArgument;

// for "Thread"

EXTERN ThreadInfo *GetCurrentThreadInfo()
{
    ThreadInfo *pThreadInfo;
    Aura_ThreadId iThreadId = (Aura_ThreadId)getpid();

    Lock(s_ThreadLock);
    ForEachDLinkNode(ThreadInfo *, pThreadInfo, &g_ThreadInfoList) {
        if(iThreadId == pThreadInfo->m_iThreadId){
            Unlock(s_ThreadLock);
            return pThreadInfo;
        }
    }
    Unlock(s_ThreadLock);

    return AURA_NULL;
}

void SIGINTCatcher(int sig)
{
    ThreadInfo *pThreadInfo;

    pThreadInfo = GetCurrentThreadInfo();
    assert(AURA_NULL != pThreadInfo);
    if(WAITING & pThreadInfo->m_uState){
        pThreadInfo->m_uState |= INTERRUPT;
        pThreadInfo->m_uState &= ~WAITING;
    }

}

void SIGALRMCatcher(int sig)
{
    ThreadInfo *pThreadInfo;

    pThreadInfo = GetCurrentThreadInfo();
    assert(AURA_NULL != pThreadInfo);
    if(WAITING & pThreadInfo->m_uState){
        pThreadInfo->m_uState |= TIMEOUT;
        pThreadInfo->m_uState &= ~WAITING;
    }
}

void SIGUSR1Catcher(int sig)
{
    ThreadInfo *pThreadInfo;

    pThreadInfo = GetCurrentThreadInfo();
    assert(AURA_NULL != pThreadInfo);
    if(WAITING & pThreadInfo->m_uState){
        pThreadInfo->m_uState &= ~WAITING;
    }
}

int SetHandler (
        int sig,
        void (*func)(int))
{
    struct sigaction SigAct;

    SigAct.sa_flags = SA_RESTART|SA_NOCLDSTOP;//BUGBUG:May restart the semop

    SigAct.sa_handler = (void (*)(int))func;
    sigemptyset( &SigAct.sa_mask );
    sigaddset( &SigAct.sa_mask, SIGINT );
    sigaddset( &SigAct.sa_mask, SIGALRM );
    sigaddset( &SigAct.sa_mask, SIGUSR1 );

    return sigaction( sig, &SigAct, AURA_NULL );
}


int SetSignalCatcher()
{
    int ret;

    ret = SetHandler(SIGINT, SIGINTCatcher);
    if(-1 == ret){
        return ret;
    }

    ret = SetHandler(SIGALRM, SIGALRMCatcher);
    if(-1 == ret){
        return ret;
    }

    ret = SetHandler(SIGUSR1, SIGUSR1Catcher);
    if(-1 == ret){
        return ret;
    }

    return 0;
}

AURA_API AuraThread_GetCurrentId(
        /* [out]  */ Aura_ThreadId * pThreadId)
{
    if(AURA_NULL == pThreadId){
        PERROR("Error: Get Current thread Id failed! \
            file:%s. line:%d. \n",
            __FILE__, __LINE__);
        return AURA_E_INVALID_ARGUMENT;
    }

    *pThreadId = getpid();

    return AURA_NOERROR;
}


AURA_API_(void) AuraThread_Quit(
        /* [in] */ Aura_QuitCode quitCode)
{
    ThreadInfo *pThreadInfo = GetCurrentThreadInfo();

    if(AURA_NULL != pThreadInfo){
        pThreadInfo->m_uState |= QUIT;
    }

    _exit(quitCode);
}


int StartThread(Aura_PVoid pArg)
{
    ThreadArgument * pThreadArg = (ThreadArgument *)pArg;
    ThreadInfo *pThreadInfo;
    PAuraThreadMain pEntry;
    Aura_PVoid           pArgs;
    Aura_Bool         bIsSuspend;

    pEntry = pThreadArg->m_pEntry;
    pArgs = pThreadArg->m_pArgs;
    bIsSuspend = pThreadArg->m_bIsSuspend;
    pThreadInfo = pThreadArg->m_pThreadInfo;
    free(pThreadArg);

    pThreadInfo->m_iThreadId = (Aura_ThreadId)getpid();

    if(bIsSuspend){
        AuraThread_Suspend((Aura_Handle)pThreadInfo);
    }

    pEntry(pArgs);

    AuraThread_Quit(0);

    return 0;
}


#define STACK_SIZE 4*1024*1024

AURA_API AuraThread_Create(
        /* [in] */ PAuraThreadMain pEntry,
        /* [in] */ Aura_PVoid pArgument,
        /* [in] */ Aura_ThreadCreationFlags creationFlags,
        /* [out] */ Aura_Handle * phThread,
        /* [out] */ Aura_ThreadId * pThreadId)
{
    ThreadArgument * pArg;
    char *pStack;
    ThreadInfo *pThreadInfo;
    int tid;

    pArg = (ThreadArgument *)malloc (sizeof(ThreadArgument));
    if(AURA_NULL == pArg){
        PERROR("Error: Create Thread failed! \
        file:%s. line:%d. \n",
        __FILE__, __LINE__);
        return AURA_E_OUT_OF_MEMORY;
    }

    pStack = (char *)malloc(STACK_SIZE);
    if(AURA_NULL == pStack){
        PERROR("Error: Create Thread failed! \
        file:%s. line:%d. \n",
        __FILE__, __LINE__);

        free(pArg);

        return AURA_E_OUT_OF_MEMORY;
    }

    pThreadInfo = new ThreadInfo();
    if(AURA_NULL == pThreadInfo){
        PERROR("Error: Create Thread failed! \
        file:%s. line:%d. \n",
        __FILE__, __LINE__);

        free(pArg);
        free(pStack);

        return AURA_E_OUT_OF_MEMORY;
    }

    pThreadInfo->m_pStack = pStack;
    pArg->m_pEntry = pEntry;
    pArg->m_pArgs = pArgument;
    pArg->m_pThreadInfo = pThreadInfo;
    if (creationFlags & Aura_ThreadCreationFlag_Unstarted) {
        pArg->m_bIsSuspend = AURA_TRUE;
    }else {
        pArg->m_bIsSuspend = AURA_FALSE;
    }

    Lock(s_ThreadLock);
    g_ThreadInfoList.InsertNext(pThreadInfo);
    Unlock(s_ThreadLock);

    tid = clone(StartThread,
        pStack + STACK_SIZE - 1,
        CLONE_FS|CLONE_FILES|CLONE_VM|CLONE_SIGHAND,//|SIGCHLD,
        (Aura_PVoid)pArg);
    if(-1 == tid){
        PERROR("Error: Create Thread failed! \
        file:%s. line:%d. \n",
        __FILE__, __LINE__);

        free(pArg);
        free(pStack);
        Lock(s_ThreadLock);
        pThreadInfo->Detach();
        Unlock(s_ThreadLock);
        delete pThreadInfo;

        return AURA_E_INVALID_OPERATION;
    }

    pThreadInfo->m_iThreadId = (Aura_ThreadId)tid;

    if(AURA_NULL != phThread){
        *phThread = (Aura_Handle *)pThreadInfo;
    }
    if(AURA_NULL != pThreadId){
        *pThreadId = (Aura_ThreadId)tid ;
    }

    return AURA_NOERROR;
}

AURA_API AuraThread_Open(
        /* [in] */ Aura_ThreadId threadId,
        /* [out] */ Aura_Handle * phThread)
{

    ThreadInfo *pThreadInfo;

    if((0 == threadId)
        || (AURA_NULL == phThread)){
        PERROR("Error: Thread Open failed! \
        file:%s. line:%d. \n",
        __FILE__, __LINE__);
        return AURA_E_INVALID_ARGUMENT;
    }
    Lock(s_ThreadLock);
    ForEachDLinkNode(ThreadInfo *, pThreadInfo, &g_ThreadInfoList) {
        if(threadId == pThreadInfo->m_iThreadId){
            *phThread = (Aura_Handle)pThreadInfo;
            Unlock(s_ThreadLock);
            return AURA_NOERROR;
        }
    }
    Unlock(s_ThreadLock);

    return AURA_E_DOES_NOT_EXIST;
}

AURA_API AuraThread_Resume(
        /* [in] */ Aura_Handle hThread)
{
    ThreadInfo *pThreadInfo = (ThreadInfo *)hThread;

    if((AURA_NULL == pThreadInfo)
        || (!IsValidHandle(ThreadInfo, pThreadInfo))){
        PERROR("Error: Thread Resume failed! \
        file:%s. line:%d. \n",
        __FILE__, __LINE__);
        return AURA_E_INVALID_ARGUMENT;
    }

    if(SUSPENDING & pThreadInfo->m_uState){
        pThreadInfo->m_uState &= ~SUSPENDING;
        kill(pThreadInfo->m_iThreadId, SIGCONT);
    }

    return AURA_NOERROR;
}

AURA_API AuraThread_Suspend(
        /* [in] */ Aura_Handle hThread)
{
    ThreadInfo *pThreadInfo = (ThreadInfo *)hThread;

    if((AURA_NULL == pThreadInfo)
        || (!IsValidHandle(ThreadInfo, pThreadInfo))){
        PERROR("Error: Thread Suspend failed! \
        file:%s. line:%d. \n",
        __FILE__, __LINE__);
        return AURA_E_INVALID_ARGUMENT;
    }

    pThreadInfo->m_uState |= SUSPENDING;

    kill(pThreadInfo->m_iThreadId, SIGSTOP);

    return AURA_NOERROR;
}

AURA_API AuraThread_Join(
        /* [in] */ Aura_Handle hThread,
        /* [in] */ Aura_Millisecond timeOut,
        /* [out] */ Aura_WaitResult * pResult)
{
#if 0
    Aura_ECode ec = AURA_NOERROR;
    Aura_QuitCode quitCode;
    ThreadInfo *pThreadInfo = (ThreadInfo *)hThread;

    if((AURA_NULL == pThreadInfo)
        || (!IsValidHandle(ThreadInfo, pThreadInfo))){
        PERROR("Error: Thread Join failed! \
        file:%s. line:%d. \n",
        __FILE__, __LINE__);
        return AURA_E_INVALID_ARGUMENT;
    }

    if(0 == timeOut){
        //may thread is not the child of join thread, waitpid will fail;
    }

    if(AURA_INFINITE != timeOut){
        //settimer
        //sigaction
    setitimer(int which, const struct itimerval *value, struct itimer-
                  val *ovalue);
    }

    pThreadInfo->m_uState = WAITING;

    while(WAITING & pThreadInfo->m_uState){
        ret = waitpid
        int iErrno = errno;
        if(iErrno == EINTR) {
            //times out
            //interupt

        }
    }

    //setitimer

    return ec;
#endif

    return AURA_E_NOT_IMPLEMENTED;
}

AURA_API AuraThread_Abort(
        /* [in] */ Aura_Handle hThread,
        /* [in] */ Aura_QuitCode quitCode)
{
    ThreadInfo *pThreadInfo = (ThreadInfo *)hThread;

    if((AURA_NULL == pThreadInfo)
        || (!IsValidHandle(ThreadInfo, pThreadInfo))){
        PERROR("Error: Thread Abort failed! \
        file:%s. line:%d. \n",
        __FILE__, __LINE__);
        return AURA_E_INVALID_ARGUMENT;
    }

    pThreadInfo->m_uState |= QUIT;
    kill(pThreadInfo->m_iThreadId, SIGKILL);

    return AURA_NOERROR;
}

AURA_API AuraThread_Interrupt(
        /* [in] */ Aura_Handle hThread)
{
    //may be use the teb for ipc
    ThreadInfo *pThreadInfo = (ThreadInfo *)hThread;

    if((AURA_NULL == pThreadInfo)
        || (!IsValidHandle(ThreadInfo, pThreadInfo))){
        PERROR("Error: Thread Interrupt failed! \
        file:%s. line:%d. \n",
        __FILE__, __LINE__);
        return AURA_E_INVALID_ARGUMENT;
    }

    pThreadInfo->m_uState |= INTERRUPT;
    kill(pThreadInfo->m_iThreadId, SIGINT);

    return AURA_NOERROR;

}

AURA_API AuraThread_Destroy(
        /* [in] */ Aura_Handle hThread)
{
    ThreadInfo *pThreadInfo = (ThreadInfo *)hThread;

    if((AURA_NULL == pThreadInfo)
        || (!IsValidHandle(ThreadInfo, pThreadInfo))){
        PERROR("Error: Thread Destroy failed! \
        file:%s. line:%d. \n",
        __FILE__, __LINE__);
        return AURA_E_INVALID_ARGUMENT;
    }

    if(AURA_NULL != pThreadInfo->m_pStack){
        free(pThreadInfo->m_pStack);
        pThreadInfo->m_pStack = AURA_NULL;
    }

    Lock(s_ThreadLock);
    pThreadInfo->Detach();
    Unlock(s_ThreadLock);

    delete pThreadInfo;

    return AURA_NOERROR;
}

AURA_API AuraThread_GetPriority(
        /* [in] */ Aura_Handle hThread,
        /* [out] */ Aura_ThreadPriority * pPriority)
{
    ThreadInfo *pThreadInfo = (ThreadInfo *)hThread;
    struct sched_param sSchedParam;


    if((AURA_NULL == pPriority)
        ||(AURA_NULL == pThreadInfo)
        || (!IsValidHandle(ThreadInfo, pThreadInfo))){
        PERROR("Error: Thread Get Priority failed! \
        file:%s. line:%d. \n",
        __FILE__, __LINE__);
        return AURA_E_INVALID_ARGUMENT;
    }

    if(-1 == sched_getparam(pThreadInfo->m_iThreadId, &sSchedParam)){
        PERROR("Error: Get Thread Priority failed! errno:%d\
            file:%s. line:%d. \n",
            errno, __FILE__, __LINE__);
        return AURA_E_INVALID_OPERATION;
    }

    *pPriority = sSchedParam.sched_priority;

    return AURA_NOERROR;
}

AURA_API AuraThread_SetPriority(
        /* [in] */ Aura_Handle hThread,
        /* [in] */ Aura_ThreadPriority priority)
{
    ThreadInfo *pThreadInfo = (ThreadInfo *)hThread;
    struct sched_param sSchedParam;

    if((AURA_NULL == pThreadInfo)
        || (!IsValidHandle(ThreadInfo, pThreadInfo))){
        PERROR("Error: Thread Set Priority failed! \
        file:%s. line:%d. \n",
        __FILE__, __LINE__);
        return AURA_E_INVALID_ARGUMENT;
    }

    if(-1 == sched_getparam(pThreadInfo->m_iThreadId, &sSchedParam)){
        PERROR("Error: Set Thread Priority failed! errno:%d\
            file:%s. line:%d. \n",
            errno, __FILE__, __LINE__);
        return AURA_E_INVALID_OPERATION;
    }

    sSchedParam.sched_priority = priority;

    if(-1 == sched_setparam(pThreadInfo->m_iThreadId, &sSchedParam)){
        PERROR("Error: Set Thread Priority failed! errno:%d\
            file:%s. line:%d. \n",
            errno, __FILE__, __LINE__);
    }

    return AURA_NOERROR;

}

AURA_API AuraThread_GetLifespan(
        /* [in] */ Aura_Handle hThread,
        /* [out] */ Aura_SystemTime * pStartTime,
        /* [out] */ Aura_SystemTime * pQuitTime)
{

    return AURA_E_NOT_IMPLEMENTED;

}

AURA_API AuraThread_GetProcessorTime(
        /* [in] */ Aura_Handle hThread,
        /* [out] */ Aura_Millisecond * pUserTime,
        /* [out] */ Aura_Millisecond * pPrivilegedTime)
{
    struct rusage usage;
    int ret;

    if((AURA_NULL == pUserTime)
        || (AURA_NULL == pPrivilegedTime))
    {
        PERROR("Error: Get Thread Processor Time failed! \
        file:%s. line:%d. \n",
        __FILE__, __LINE__);
        return AURA_E_INVALID_ARGUMENT;
    }

    ThreadInfo *pThreadInfo = (ThreadInfo *)hThread;

    if((AURA_NULL == pThreadInfo)
        || (!IsValidHandle(ThreadInfo, pThreadInfo))){
        PERROR("Error: Get Thread Processor Time failed! \
        file:%s. line:%d. \n",
        __FILE__, __LINE__);
        return AURA_E_INVALID_ARGUMENT;
    }


    ret = getrusage(RUSAGE_SELF, &usage);
    if(-1 == ret){
        PERROR("Error: Get Thread Processor Time failed! error number:%d.\
        errno, file:%s. line:%d. \n",
        __FILE__, __LINE__);
        return AURA_E_INVALID_OPERATION;
    }

    *pUserTime = usage.ru_utime.tv_sec*1000 + usage.ru_utime.tv_usec/1000;
    *pPrivilegedTime = usage.ru_stime.tv_sec*1000 + usage.ru_stime.tv_usec/1000;

    return AURA_NOERROR;
}

AURA_API AuraThread_GetQuitCode(
        /* [in] */ Aura_Handle hThread,
        /* [out] */ Aura_QuitCode * pQuitCode)
{

    return AURA_E_NOT_IMPLEMENTED;

}

AURA_API AuraThread_Sleep(
        /* [in] */ Aura_Millisecond timeOut,
        /* [out] */ Aura_WaitResult * pResult)
{

    struct timespec tTimeReq, tTimeRem;
    ThreadInfo *pThreadInfo;
    int ret = 0;

    pThreadInfo = GetCurrentThreadInfo();
    assert(AURA_NULL != pThreadInfo);

    tTimeReq.tv_sec = timeOut / (1000);
    tTimeReq.tv_nsec = (timeOut % (1000)) * 1000 *1000;

    pThreadInfo->m_uState &= WAITING;

    do {
        ret = nanosleep(&tTimeReq, &tTimeRem);
        if(-1 == ret){
            if(EINTR == errno){
                if(pThreadInfo->m_uState & INTERRUPT){
                    pThreadInfo->m_uState &= ~INTERRUPT;
                    if(AURA_NULL != pResult){
                        *pResult = Aura_WaitResult_Interrupted;
                    }
                    return AURA_NOERROR;
                }else {
                    memcpy(&tTimeReq, &tTimeRem, sizeof(struct timespec));
                }
            } else {
                return AURA_E_INVALID_OPERATION;
            }
        }
    } while (-1 == ret);

    if(AURA_NULL != pResult){
        *pResult = Aura_WaitResult_TimedOut;
    }

    return AURA_NOERROR;
}

AURA_API AuraThread_Yield()
{
    sched_yield();
    return AURA_NOERROR;
}


// for "TLS"

/* TLS slot bitmap. Its size in bits must be the same as TLS_SLOT_SIZE */
static Aura_UInt64 s_TlsSlotFields;
static Aura_Handle s_TlsLock;

AURA_API AuraTls_Allocate(
    /* [out] */ Aura_UInt32 * pIndex)
{
    Aura_UInt32 i;

    Lock(s_TlsLock);
    for(i = 0; i < sizeof(s_TlsSlotFields) * 8; i++)
    {
        if ((s_TlsSlotFields & ((Aura_UInt64) 1 << i)) == 0)
        {
            s_TlsSlotFields |= ((Aura_UInt64) 1 << i);
            break;
        }
    }
    if (i == sizeof(s_TlsSlotFields) * 8)
    {
        Unlock(s_TlsLock);
        return AURA_E_OUT_OF_MEMORY;
    }

    *pIndex = i;

    ThreadInfo *pThreadInfo;
    /* Initialize all threads' values to zero for this uIndex. */
    Lock(s_ThreadLock);
    ForEachDLinkNode(ThreadInfo *, pThreadInfo, &g_ThreadInfoList) {
        pThreadInfo->m_pTlsSlots[i] = AURA_NULL;
    }
    Unlock(s_ThreadLock);

    Unlock(s_TlsLock);

    return AURA_NOERROR;
}

AURA_API AuraTls_Free(
    /* [in]  */ Aura_UInt32 uIndex)
{

    if (uIndex == (Aura_UInt32) -1 || uIndex >= TLS_SLOT_SIZE)
    {
        return AURA_E_INVALID_ARGUMENT;
    }

    Lock(s_TlsLock);
    s_TlsSlotFields &= ~((Aura_UInt64) 1 << uIndex);
    Unlock(s_TlsLock);

    return AURA_NOERROR;
}

AURA_API AuraTls_GetValue(
    /* [in]  */ Aura_UInt32 uIndex,
    /* [out] */ Aura_PVoid * ppValue)
{

    Aura_PVoid pTlsValue = (Aura_PVoid)-1;
    ThreadInfo *pThreadInfo;

    if (uIndex == (Aura_UInt32) -1
        ||uIndex >= TLS_SLOT_SIZE
        ||AURA_NULL == ppValue)
    {
        return AURA_E_INVALID_ARGUMENT;
    }

    pThreadInfo = GetCurrentThreadInfo();
    assert(pThreadInfo);
    if (pThreadInfo == AURA_NULL){
        return AURA_E_INVALID_OPERATION;
    }
    pTlsValue = pThreadInfo->m_pTlsSlots[uIndex];

    *ppValue = pTlsValue;

    return AURA_NOERROR;
}

AURA_API AuraTls_SetValue(
    /* [in]  */ Aura_UInt32 uIndex,
    /* [in]  */ Aura_PVoid pValue)
{

    ThreadInfo *pThreadInfo;

    if (uIndex == (Aura_UInt32) -1 || uIndex >= TLS_SLOT_SIZE)
    {
        return AURA_E_INVALID_ARGUMENT;
    }

    pThreadInfo = GetCurrentThreadInfo();
    assert(pThreadInfo);
    if (pThreadInfo == AURA_NULL){
        return AURA_E_INVALID_OPERATION;
    }

    pThreadInfo->m_pTlsSlots[uIndex] = pValue;

    return AURA_NOERROR;
}


void __attribute__((constructor)) process_init()
{
    ThreadInfo *pThreadInfo;
    Aura_ECode ec;

    //Record start time
    gettimeofday(&g_tvStartTime, AURA_NULL);

    //Main thread info set up
    pThreadInfo = new ThreadInfo();
    if(AURA_NULL == pThreadInfo){
        PERROR("Error: set up main thread info failed! \
        file:%s. line:%d. \n",
        __FILE__, __LINE__);
    }

    pThreadInfo->m_iThreadId = (Aura_ThreadId)getpid();

    g_processId = pThreadInfo->m_iThreadId;
    PTRACE("Init process id:%d.\n", g_processId);

    ec = CreateLock(&s_ThreadLock);
    if(AURA_FAILED(ec)){
        PERROR("Error: set up main thread Lock failed! \
        file:%s. line:%d. \n",
        __FILE__, __LINE__);
    }

    ec = CreateLock(&s_TlsLock);
    if(AURA_FAILED(ec)){
        PERROR("Error: set up TLS lock failed! \
        file:%s. line:%d. \n",
        __FILE__, __LINE__);
    }

    ec = CreateModuleLock();
    if(AURA_FAILED(ec)){
        PERROR("Error: set up Module lock failed! \
        file:%s. line:%d. \n",
        __FILE__, __LINE__);
    }

    ec = InitVirtualMemory();
    if(AURA_FAILED(ec)){
        PERROR("Error: set up Virtual Memory lock failed! \
        file:%s. line:%d. \n",
        __FILE__, __LINE__);
    }

    g_ThreadInfoList.Initialize();
    g_ThreadInfoList.InsertNext(pThreadInfo);


    SetSignalCatcher();
}

void __attribute__((destructor)) process_fini()
{
    DestroyLock(s_TlsLock);
    DestroyLock(s_ThreadLock);
    DestroyModuleLock();
    DeleVirtualMemory();
}

EXTERN void _AllThread_Kill()
{
    ThreadInfo *pThreadInfo, *pCurrentThreadInfo;
    pCurrentThreadInfo = GetCurrentThreadInfo();

    Lock(s_ThreadLock);
    while(&g_ThreadInfoList != g_ThreadInfoList.Next()){
        pThreadInfo = (ThreadInfo *)g_ThreadInfoList.Next();

        if((!(QUIT & pThreadInfo->m_uState))
            &&(pCurrentThreadInfo != pThreadInfo)){
            kill(pThreadInfo->m_iThreadId, SIGKILL);
        }

        pThreadInfo->Detach();

        delete pThreadInfo;
    }
    Unlock(s_ThreadLock);

}

EXTERN void _AllThread_SetPriority(Aura_ThreadPriorityRank PriorityRank)
{
    ThreadInfo *pThreadInfo;
    Lock(s_ThreadLock);
    ForEachDLinkNode(ThreadInfo *, pThreadInfo, &g_ThreadInfoList) {
        AuraThread_SetPriority((Aura_Handle)pThreadInfo, PriorityRank);
    }
    Unlock(s_ThreadLock);
}

EXTERN void _AllThread_GetPriority(Aura_ThreadPriorityRank *pPriorityRank)
{
    ThreadInfo *pThreadInfo;
    pThreadInfo = GetCurrentThreadInfo();
    assert(AURA_NULL != pThreadInfo);

    AuraThread_GetPriority((Aura_Handle)pThreadInfo, pPriorityRank);
}

//#define DEBUG_AURA_THREADS
#ifdef DEBUG_AURA_THREADS

void threadfunc(Aura_PVoid pArg)
{
    Aura_ThreadId iThreadId;
    AuraThread_GetCurrentId(&iThreadId);
    while(1){
        printf("thread id:%d. arg:%d.\n", iThreadId, (int)pArg);
        AuraThread_Sleep((int)pArg, AURA_NULL);
        AuraThread_Yield();
    }
}

int testThreadSuspendAndResume()
{
    Aura_Handle hThread[5];
    Aura_ThreadId Aura_ThreadId[5];
    Aura_ThreadPriority priority = 0xFF;
    int i;

    AuraThread_Create(
        threadfunc,
        (Aura_PVoid)500,
        Aura_ThreadCreationFlag_Unstarted,
        AURA_NULL,
        &Aura_ThreadId[0]);
    printf("In main created thread :%d.\n", Aura_ThreadId[0]);

    AuraThread_Open(Aura_ThreadId[0], &hThread[0]);

    printf("Press any key to start the thread:%d.\n", Aura_ThreadId[0]);
    getchar();
    AuraThread_Resume(hThread[0]);

    printf("Press any key to suspend the thread:%d.\n", Aura_ThreadId[0]);
    getchar();
    AuraThread_Suspend(hThread[0]);

    printf("Press any key to resume the thread:%d.\n", Aura_ThreadId[0]);
    getchar();
    AuraThread_Resume(hThread[0]);

    printf("Press any key to suspend the thread:%d and get priority.\n", Aura_ThreadId[0]);
    getchar();
    AuraThread_Suspend(hThread[0]);
    AuraThread_GetPriority(hThread[0], &priority);
    printf("Thread:%d priority:%d.\n", Aura_ThreadId[0], priority);

    priority++;
    printf("Press any key to set the thread:%d priority:%d and resume it.\n", Aura_ThreadId[0], priority);
    getchar();
    AuraThread_SetPriority(hThread[0], priority);
    AuraThread_Resume(hThread[0]);

    Aura_ECode ec;
    for(i = 1; i < 5; i++){

        ec = AuraThread_Create(
            threadfunc,
            (Aura_PVoid)(i*500),
            0,
            &hThread[i],
            &Aura_ThreadId[i]);
        if(AURA_FAILED(ec)){
            printf("^^^^^^^^^^^^^^^^^^^^^%d\n", i);
        }
    }

    int c = 0;
    while((char)c != 'q'){
        if(i >= 5){
            i = 0;
        }
        printf("Press any key to interrupt the thread:%d.\n", Aura_ThreadId[i]);
        c = getchar();
        AuraThread_Interrupt(hThread[i]);
        i++;
    }
    getchar();

    printf("Press any key to kill all threads.\n");
    getchar();

    for(i = 0; i < 5; i++){
        AuraThread_Abort(hThread[i], 1);
        AuraThread_Destroy(hThread[i]);
    }

    return 0;
}

Aura_Handle g_hMutex;

void threadfuncWaitMutex(Aura_PVoid pArg)
{
    Aura_ThreadId iThreadId;
    Aura_WaitResult result;
    Aura_ECode ec;

    AuraThread_GetCurrentId(&iThreadId);
    while(1){
        printf("****id:%d****time out:%d*****\n", iThreadId, (Aura_Millisecond)pArg);
        ec = AuraMutex_Lock(g_hMutex, (Aura_Millisecond)pArg, &result);
        if(AURA_FAILED(ec)){
            printf("AURA_FAILED lock thread id:%d.\n", iThreadId);
            return;
        }
        if(Aura_WaitResult_OK != result){
            printf("Thread:%d time out.\n", iThreadId);
            AuraThread_Sleep(1000, &result);
            continue;
        }
        printf("Enter the mutex thread id:%d.\n", iThreadId);
        AuraMutex_Unlock(g_hMutex);
    }

    return ;
}

int threadMutexTimeOutTest()
{
    Aura_Handle hThread[2];
    Aura_ThreadId iThreadId;
    Aura_WaitResult result;
    int i = 0;
    Aura_ECode ec;

    AuraThread_GetCurrentId(&iThreadId);

    AuraMutex_Create(AURA_NULL, AURA_FALSE, &g_hMutex);

    AuraMutex_Lock(g_hMutex, AURA_INFINITE, &result);

    for(i = 0; i < 2; i++){

        ec = AuraThread_Create(
            threadfuncWaitMutex,
            (Aura_PVoid)(i*5000 + 1000),
            0,
            &hThread[i],
            AURA_NULL);
        if(AURA_FAILED(ec)){
            printf("^^^^^^^^^^^^^^^^^^^^^%d\n", i);
        }
    }
    getchar();
    AuraMutex_Unlock(g_hMutex);

    for(i = 0; i < 2; i++){
        AuraThread_Abort(hThread[i], 1);
        AuraThread_Destroy(hThread[i]);
    }

    AuraMutex_Destroy(g_hMutex);
}

int main ()
{
    return threadMutexTimeOutTest();
}

#endif //DEBUG_AURA_THREADS
